
package de.justphil.tcg.tcgserver.game.mechanics.gui;

import javax.swing.JFrame;

import de.justphil.tcg.tcgserver.game.mechanics.config.Config;
import de.justphil.tcg.tcgserver.game.mechanics.game.Game;
import de.justphil.tcg.tcgserver.game.mechanics.game.OnGameProgressListener;
import de.justphil.tcg.tcgserver.game.mechanics.game.OnUserInteractionListener;
import de.justphil.tcg.tcgserver.game.mechanics.game.UserInteractionObservable;
import de.justphil.tcg.tcgserver.game.mechanics.property.PropertyFactory;

import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.LinkedList;
import java.util.List;

public class Board implements OnGameProgressListener, UserInteractionObservable {
	
	private JFrame							frame;
	private List<OnUserInteractionListener>	onUserInteractionListeners;
	private Slot[][]						slots;
	private Slot							activeSlot;
	private Game							game;
	
	/**
	 * Constructor
	 */
	public Board(Game game) {
	
		this.game = game;
		this.slots = new Slot[Config.NUM_PLAYERS][Config.NUM_SLOTS_PER_PLAYER];
		this.onUserInteractionListeners = new LinkedList<OnUserInteractionListener>();
		initialize();
	}
	
	public void setGame(Game game) {
	
		assert game != null;
		this.game = game;
	}
	
	public void exit(){
		frame.dispose();
	}
	
	@Override
	public void addOnUserInteractionListener(OnUserInteractionListener listener) {
	
		this.onUserInteractionListeners.add(listener);
	}
	
	@Override
	public boolean removeOnUserInteractionListener(
			OnUserInteractionListener onUserInteractionListener) {
	
		return this.onUserInteractionListeners.remove(onUserInteractionListener);
	}
	
	@Override
	public void onGameOver(int winner) {
	
		if (winner != -1) {
			for (Slot slot : slots[winner]) {
				slot.setWinner();
			}
		}
		else {
			for (int player = 0; player < Config.NUM_PLAYERS; player++) {
				for (Slot slot : slots[player]) {
					slot.setWinner();
				}
			}
		}
	}
	
	@Override
	public void onProgress(int player, int slot, long cardId, int[] propertyTypes, int life,
			int attack, int defense, int agility) {
	
		if (cardId == -1) {
			removeMonster(player, slot);
		}
		else {
			List<String> propertyStrings = new LinkedList<String>();
			propertyStrings.add(Long.toString(cardId));
			for (int propertyType : propertyTypes) {
				propertyStrings.add(PropertyFactory.getProperty(game, propertyType)
						.getTypeAsString());
			}
			setSlotValues(player, slot, Integer.toString(life), Integer.toString(attack),
					Integer.toString(defense), Integer.toString(agility), propertyStrings);
		}
	}
	
	@Override
	public void onGameInfo(int type, String text) {
	
	}
	
	@Override
	public void onSelectionRequired(int player, int slot) {
	
		setActiveSlot(player, slot);
	}
	
	@Override
	public void onResumeRequired(int player) {
	
	}
	
	/**
	 * Initialize the contents of the frame.
	 */
	private void initialize() {
	
		frame = new JFrame();
		frame.setBounds(100, 100, 800, 720);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.getContentPane().setLayout(new GridLayout(2, 3, 10, 10));
		Slot slot_00 = new Slot();
		slot_00.addMouseListener(new MouseAdapter() {
			
			@Override
			public void mouseClicked(MouseEvent e) {
			
				signalSlotSelected(0, 0);
			}
		});
		frame.getContentPane().add(slot_00);
		Slot slot_01 = new Slot();
		slot_01.addMouseListener(new MouseAdapter() {
			
			@Override
			public void mouseClicked(MouseEvent e) {
			
				signalSlotSelected(0, 1);
			}
		});
		frame.getContentPane().add(slot_01);
		Slot slot_02 = new Slot();
		slot_02.addMouseListener(new MouseAdapter() {
			
			@Override
			public void mouseClicked(MouseEvent e) {
			
				signalSlotSelected(0, 2);
			}
		});
		frame.getContentPane().add(slot_02);
		Slot slot_10 = new Slot();
		slot_10.addMouseListener(new MouseAdapter() {
			
			@Override
			public void mouseClicked(MouseEvent e) {
			
				signalSlotSelected(1, 0);
			}
		});
		frame.getContentPane().add(slot_10);
		Slot slot_11 = new Slot();
		slot_11.addMouseListener(new MouseAdapter() {
			
			@Override
			public void mouseClicked(MouseEvent e) {
			
				signalSlotSelected(1, 1);
			}
		});
		frame.getContentPane().add(slot_11);
		Slot slot_12 = new Slot();
		slot_12.addMouseListener(new MouseAdapter() {
			
			@Override
			public void mouseClicked(MouseEvent e) {
			
				signalSlotSelected(1, 2);
			}
		});
		frame.getContentPane().add(slot_12);
		frame.setVisible(true);
		this.slots[0][0] = slot_00;
		this.slots[0][1] = slot_01;
		this.slots[0][2] = slot_02;
		this.slots[1][0] = slot_10;
		this.slots[1][1] = slot_11;
		this.slots[1][2] = slot_12;
	}
	
	private void setActiveSlot(int player, int slot) {
	
		if (activeSlot != null) {
			activeSlot.setActive(false);
		}
		activeSlot = slots[player][slot];
		activeSlot.setActive(true);
	}
	
	private void deactivateActiveSlot() {
	
		if (activeSlot != null) {
			activeSlot.setActive(false);
			activeSlot = null;
		}
	}
	
	private void removeMonster(int player, int slot) {
	
		slots[player][slot].setEmty();
	}
	
	private void setSlotValues(int player, int slot, String life, String attack, String defense,
			String speed, List<String> properties) {
	
		this.slots[player][slot].setCard(life, attack, defense, speed, properties);
	}
	
	private void signalSlotSelected(int player, int slot) {
	
		for (OnUserInteractionListener onUserInteractionListener : onUserInteractionListeners) {
			deactivateActiveSlot();
			onUserInteractionListener.onSlotSelected(player, slot);
		}
	}
}
